#include "net_traffic_upload.h"

static volatile ssize_t total_send_bytes = 0;
static volatile ssize_t total_receive_bytes = 0;


static void sleep_full_seconds(unsigned int seconds)
{
	do { seconds = sleep(seconds); } while (seconds > 0);
}

static void setnonblock(int fd)
{
	int flag = fcntl(fd, F_GETFL);

	fcntl(fd, F_SETFL, flag | O_NONBLOCK);
}

static void clearnonblock(int fd)
{
	int flag = fcntl(fd, F_GETFL);

	fcntl(fd, F_SETFL, flag & ~O_NONBLOCK);
}

static int connect_timeout(int sockfd, struct sockaddr *addr)
{
	int i = 0;

	for (i = 0; i < CONNECT_TRY; i++) {
		if (connect(sockfd, addr, sizeof(struct sockaddr_in)) == 0) {
			return 0;
		} else if (errno == EISCONN) {
			return 0;
		} else if (errno == EINPROGRESS || errno == EINTR) {
			usleep(CONNECT_TIMEOUT);
		} else { return -1; }
	}
	return -1;
}


static int select_timeout(int sockfd, int is_r, int second, int usecond)
{
	struct timeval timeout;
	timeout.tv_sec = second;
	timeout.tv_usec = usecond;

	fd_set read_fdset;
	fd_set write_fdset;
	fd_set *r_fdset = NULL;
	fd_set *w_fdset = NULL;

	if (is_r) {
		FD_ZERO(&read_fdset);
    	FD_SET(sockfd, &read_fdset);
		r_fdset = &read_fdset;
	}

	if (!is_r) {
		FD_ZERO(&write_fdset);
    	FD_SET(sockfd, &write_fdset);
		w_fdset = &write_fdset;
	}

    return select(sockfd + 1, r_fdset, w_fdset, NULL, &timeout);
}


static void *upload_traffic_rpc(void *arg)
{
	while (1) {
		#if defined (NO_DATA_NO_UPLOAD)
			if ((total_send_bytes == 0) && (total_receive_bytes == 0))
					goto no_data;
		#endif

		char buf[256];
		#ifdef __x86_64__
			sprintf(buf, "GET method {\"cmd\":\"traffic\", \"cp\":\"webrtc\", \"sb\":%ld, \"rb\":%ld}",
				total_send_bytes, 
				total_receive_bytes);
		#else
			sprintf(buf, "GET method {\"cmd\":\"traffic\", \"cp\":\"webrtc\", \"sb\":%d, \"rb\":%d}",
				total_send_bytes, 
				total_receive_bytes);
		#endif

		static int port = PORT_LOW;
		if (port > PORT_HIGH) port = PORT_LOW;

		for (; port <= PORT_HIGH; ++port) {

			printf("port: %d\n", port);

			struct sockaddr_in saddr;  
			memset(&saddr, 0, sizeof(saddr));  
			saddr.sin_family = AF_INET;  
			saddr.sin_port = htons(port);
			saddr.sin_addr.s_addr = inet_addr(HOST_IP);

			// socket
			//
			int sockfd;
			if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
					goto socket_failed;
			}
			setnonblock(sockfd);
			//printf("socket\n");

			// connect
			//
			if (connect_timeout(sockfd, (struct sockaddr*)&saddr) < 0) {
					continue;
			}
			//printf("connect\n");

			// send traffic data to pear_monitor
			//
			if (write(sockfd, buf, strlen(buf)) < 0) {
				close(sockfd); 
				goto write_failed; 
			}
			//printf("write\n");

			// recv from pear_monitor
			//
			int ret = select_timeout(sockfd, 1, SELECT_TIMEOUT_SECOND, SELECT_TIMEOUT_USECOND);
			if (ret < 0) {
				perror("select");
			} else if (ret) {
        		if (read(sockfd, buf, sizeof(buf) -1) > 0) {
					if (strstr(buf, "HTTP/1.1 200 OK")) {
						total_send_bytes = 0;
						total_receive_bytes = 0;
						close(sockfd);
						break;
					}
				}
        	} else {
				printf("timeout\n");
			}

			close(sockfd);
			continue;
		}

	#if defined (NO_DATA_NO_UPLOAD)
		no_data:
	#endif
		socket_failed:
		write_failed:
			sleep_full_seconds(UPLOAD_INTERVAL);
	}
}


int main(void)
{
	pthread_t thread_id;
	pthread_create(&thread_id, NULL, upload_traffic_rpc, 0);

	while (1) {
			printf("parent thread keep alive\n");
			sleep(1);
	}
}




